import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })

export class TreeTools {

    /**
     * 根据ID查找树结构节点的对应名称
     * @param param
     *  id 要进行比对的ID，
     *  nodes 查找对象节点
     *  keyName 节点ID的名称，默认为key
     *  valueName 节点text的名称，默认title
     *  childrenName 节点的子节点集合名称 默认children
     */
    getTreeNodeName(param) {
        const valueName = param.valueName || 'title';
        const node = this.getTreeNode(param);
        if (node) {
            return node[valueName];
        }
    }

    /**
     * 根据ID查找树结构的节点
     * @param param
     *  id 要进行比对的ID，
     *  nodes 查找对象节点
     *  keyName 节点ID的名称，默认为key
     *  childrenName 节点的子节点集合名称 默认children
     */
    getTreeNode(param) {
        const id = param.id;
        const nodes = param.nodes;
        const keyName = param.keyName || 'key';
        // const valueName = param.valueName || 'title';
        const childrenName = param.childrenName || 'children';

        for (const item of nodes) { 
            if (item[keyName] === id) {
                return item;
            } else if (item[childrenName] && item[childrenName].length) {
                const _node = this.getTreeNode({
                    id,
                    nodes: item[childrenName],
                    keyName,
                    childrenName
                });
                if (_node) {
                    return _node;
                }
            }
        }
    }

    /**
     * 根据ID查找树结构节点名称
     * @param param
     *  ids 要进行比对的ID，
     *  nodes 查找对象节点
     *  keyName 节点ID的名称，默认为key
     *  valueName 节点text的名称，默认title
     *  childrenName 节点的子节点集合名称 默认children
     */
    getNodeNames(param) {
        const valueName = param.valueName || 'title';
        const nodeNames = [];
        const nodes = this.getTreeNodes(param);
        nodes.forEach(node => {
            nodeNames.push(node[valueName]);
        });
        return nodeNames.join();
    }

    /**
     * 根据ID查找树结构的节点
     * @param param
     *  ids 要进行比对的ID，
     *  nodes 查找对象节点
     *  keyName 节点ID的名称，默认为key
     *  childrenName 节点的子节点集合名称 默认children
     */
    getTreeNodes(param) {
        const ids: any[] = param.ids;
        const nodes = param.nodes;
        const keyName = param.keyName || 'key';
        // const valueName = param.valueName || 'title';
        const childrenName = param.childrenName || 'children';
        const findNodes: any[] = [];
        for (const node of nodes) {
            if (ids.includes(node[keyName])) {
                // if (node[keyName] === id) {
                findNodes.push(node);
            }
            if (node[childrenName] && node[childrenName].length) {
                const _findNodes = this.getTreeNodes({
                    ids,
                    nodes: node[childrenName],
                    keyName,
                    childrenName
                });
                if (_findNodes.length) {
                    findNodes.push(..._findNodes);
                }
            }
        }
        if (findNodes.length) {
            findNodes.sort((a: any, b: any) => {
                const idx_a = ids.indexOf(a);
                const idx_b = ids.indexOf(b);
                let res = 0;
                if (idx_a < idx_b) {
                    res = -1;
                } else if (idx_a > idx_b) {
                    res = 1;
                }
                return res
            })
        }
        return findNodes;
    }

    getPnode(param) {
        const id = param.id;
        const nodes = param.nodes;
        const keyName = param.keyName || 'key';
        // const valueName = param.valueName || 'title';
        const childrenName = param.childrenName || 'children';
        let pNode = param.pNode;

        for (const item of nodes) { 
            if (item[keyName] === id) {
                return pNode || item;
            } else if (item[childrenName] && item[childrenName].length) {
                pNode = item;
                const _node = this.getPnode({
                    id,
                    nodes: item[childrenName],
                    pNode,
                    keyName,
                    childrenName
                });
                if (_node) {
                    return _node;
                }
            }
        }
    }

    /**
     * 把树形结构的节点转化为zorro可以接受的形式
     * 具体来说就是把id和text（如果是其他名字需要通过keyName和valueName设置）
     * 的值赋值给key 和 title
     * @param param
     *  nodes
     *  selectOnlyLeaf 只能选择叶子节点
     *  keyName 节点ID的名称，默认为id
     *  valueName 节点text的名称，默认text
     *  childrenName 节点的子节点集合名称 默认children
     */
    formatTreeNodes(param) {
        const keyName = param.keyName || 'id';
        const valueName = param.valueName || 'text';
        const childrenName = param.childrenName || 'children';
        const nodes = param.nodes;
        const selectOnlyLeaf = param.selectOnlyLeaf;
        if (nodes.length) {
            nodes.forEach(node => {
                node.key = node[keyName] || '';
                node.title = node[valueName] || '';
                if (node[childrenName] && node[childrenName].length) {
                    node.children = node[childrenName];
                    if (selectOnlyLeaf) {
                        node.selectable = false;
                    }
                    node.isLeaf = false;
                    const p: any = {
                        nodes: node[childrenName],
                        keyName,
                        valueName,
                        childrenName,
                    };
                    this.formatTreeNodes(p);
                } else {
                    node.isLeaf = true;
                }
            });
        }
    }

    loopTree(param) {
        const keyName = param.keyName || 'id';
        const valueName = param.valueName || 'text';
        const childrenName = param.childrenName || 'children';
        const nodes = param.nodes;
        const logicArr: { judgeFunc, trueFunc, falseFunc?}[] = param.logicArr || [];
        if (!logicArr.length) {
            return;
        }
        if (nodes.length) {
            nodes.forEach(node => {
                if (logicArr.length) {
                    logicArr.forEach(logic => {
                        if (logic.judgeFunc) {
                            if (logic.judgeFunc(node) === true) {
                                logic.trueFunc(node);
                            } else if (logic.falseFunc) {
                                logic.falseFunc(node);
                            }
                        }
                    });
                }
                if (node[childrenName] && node[childrenName].length) {
                    const p: any = {
                        nodes: node[childrenName],
                        keyName,
                        valueName,
                        childrenName,
                        logicArr,
                    };
                    this.loopTree(p);
                }
            });
        }
    }
    // 旧的
    formatTreeNode(resdata) {
        const node: any = [];
        let count = 0;
        for (const item of resdata) {
            if (item.children) {
                node.push({
                    title: item.text,
                    key: item.id,
                    disabled: true,
                    children: []
                });
                for (const list of item.children) {
                    node[count].children.push({
                        title: list.text,
                        key: list.id,
                        isLeaf: true
                    });
                }
            } else {
                node.push({
                    title: item.text,
                    key: item.id,
                    isLeaf: true
                });
            }
            count += 1;
        }
        return node;
    }
    formatSelectNode(resdata) {
        const node: any = [];
        let count = 0;
        for (const item of resdata) {
            if (item.childselectOptions && item.childselectOptions.length) {
                node.push({
                    title: item.opName,
                    key: item.opValue,
                    disabled: true,
                    children: []
                });
                for (const list of item.childselectOptions) {
                    node[count].children.push({
                        title: list.opName,
                        key: list.opValue,
                        isLeaf: true
                    });
                }
            } else {
                node.push({
                    title: item.opName,
                    key: item.opValue,
                    isLeaf: true
                });
            }
            count += 1;
        }
        return node;
    }
}
